<template>
  <canvas @mousedown="mousedown"></canvas>
</template>

<script setup>
import _ from 'lodash';
const props = defineProps({
  canvasConfig: {
    type: Object,
    default: () => {},
  },
  initClient: {
    type: Object,
    default: () => ({}),
  },
});

const emits = defineEmits([]);

const baseConfig = {
  width: 500, // 宽度
  height: 500, // 高度
  lineWidth: 5, // 线宽
  strokeStyle: '#303133', // 线条颜色
  lineCap: 'round', // 设置线条两端圆角
  lineJoin: 'round', // 线条交汇处圆角
};

let canvas = null;
let ctx = null;

// 保存上次绘制的 坐标及偏移量
let client = {
  offsetX: 0, // 偏移量
  offsetY: 0,
  endX: 0, // 坐标
  endY: 0,
};

onMounted(() => {
  nextTick(() => {
    canvas = document.querySelector('canvas');
    let a = canvas.getBoundingClientRect();
    ctx = canvas.getContext('2d');
    // 设置宽高
    canvas.width = config.value.width;
    canvas.height = config.value.height;
    ctx.strokeStyle = config.value.strokeStyle;
    ctx.lineWidth = config.value.lineWidth;
    ctx.lineCap = config.value.lineCap;
    ctx.lineJoin = config.value.lineJoin;
  });
});

const mousedown = e => {
  init(e);
};

const config = computed(() => {
  return _.merge({}, baseConfig, props.canvasConfig);
});

// 设置画笔颜色
const setStrokeStyle = val => {
  ctx.strokeStyle = val;
};

// 初始化
const init = event => {
  // 获取偏移量及坐标
  const { offsetX, offsetY, pageX, pageY } = event;
  // 修改上次的偏移量及坐标
  client.offsetX = offsetX;
  client.offsetY = offsetY;
  client.endX = pageX;
  client.endY = pageY;

  // 监听 鼠标移动
  window.addEventListener('mousemove', draw);
  // 监听 鼠标弹起
  window.addEventListener('mouseup', closeDraw);
};

// 如果初始有图纸，设置初始图纸
const initCanvas = url => {
  clearDraw();
  let imgEle = new Image();
  imgEle.src = url;
  imgEle.setAttribute('crossOrigin', 'Anonymous');

  imgEle.onload = function () {
    let imgW = imgEle.width || config.value.width;
    let imgH = imgEle.height || config.value.height;
    let setImgW = config.value.width;
    let setImgH = config.value.height;
    let x = 0;
    let y = 0;

    if (imgW <= setImgW) {
      x = (setImgW - imgW) / 2;
      setImgW = imgW;
    } else {
      let wScale = setImgW / imgW;
      setImgH = imgH * wScale > config.value.height ? config.value.height : imgH * wScale;
      y = (config.value.height - setImgH) / 2;
    }
    if (imgH <= setImgH) {
      y = (setImgH - imgH) / 2;
      setImgH = imgH;
    } else {
      let hScale = setImgH / imgH;
      setImgW = imgW * hScale > config.value.width ? config.value.width : imgW * hScale;
      x = (config.value.width - setImgW) / 2;
    }
    ctx.drawImage(imgEle, x, y, setImgW, setImgH);
  };
};

// 绘制
const draw = event => {
  // 清除以上一次 beginPath 之后的所有路径，进行绘制
  ctx.beginPath();
  const x = event.clientX - event.offsetX;
  const y = event.clientY - event.offsetY;

  // 设置画线起始点位
  ctx.moveTo(client.endX - x, client.endY - y);
  // 获取当前坐标点位
  const { pageX, pageY } = event;
  // 修改最后一次绘制的坐标点
  client.endX = pageX;
  client.endY = pageY;
  // 根据坐标点位移动添加线条
  ctx.lineTo(pageX - x, pageY - y);
  // 绘制
  ctx.stroke();
};

// 结束绘制
const closeDraw = () => {
  // 结束绘制
  ctx.closePath();
  // 移除鼠标移动或手势移动监听器
  window.removeEventListener('mousemove', draw);
};

// 清空画布
const clearDraw = () => {
  // 清空当前画布上的所有绘制内容
  ctx.clearRect(0, 0, config.value.width, config.value.height);
};

const canvasHandler = callback => {
  if (isCanvasBlank(canvas)) {
    callback && callback(null);
    return;
  }

  canvas.toBlob(blob => {
    let obj = {
      blob,
      file: new File([blob], 'sign.png', { type: 'image/png' }),
      imgBase64: canvas.toDataURL('image/png'),
    };
    callback && callback(obj);
  });
};

// 保存-将画布内容保存为图片
const downlaodPNG = () => {
  // 将canvas上的内容转成blob流
  canvas.toBlob(blob => {
    // 获取当前时间并转成字符串，用来当做文件名
    const date = Date.now().toString();
    // 创建一个 a 标签
    const a = document.createElement('a');
    // 设置 a 标签的下载文件名
    a.download = `${date}.png`;
    // 设置 a 标签的跳转路径为 文件流地址
    a.href = URL.createObjectURL(blob);
    // 手动触发 a 标签的点击事件
    a.click();
    // 移除 a 标签
    a.remove();
  });
};

//验证canvas画布是否为空
function isCanvasBlank(canvas) {
  let blank = document.createElement('canvas'); //系统获取一个空canvas对象
  blank.width = canvas.width;
  blank.height = canvas.height;
  let canvasData = canvas.toDataURL && canvas.toDataURL();
  let blankData = blank.toDataURL && blank.toDataURL();
  return canvasData == blankData; //比较值相等则为空
}

defineExpose({ clearDraw, downlaodPNG, canvasHandler, initCanvas, setStrokeStyle });
</script>

<style scoped lang="scss"></style>
